import logging
import unittest
import sys


import os

""" Models Init """

import google.appengine.ext.db as db

class Song(db.Model):
  composer = db.StringProperty()



class IndexTest(object):

#  def setUp(self):
#      self.application = webapp.WSGIApplication([('/', index.IndexHandler)], debug=True)

#  def test_put(self):
#      logging.debug("song key: " + str(Song(composer="Kevin", key_name="s1234").put()))
  @classmethod
  def put_xxx(cls, limit, offset=0):
      logging.debug("song key: %s..%s", offset, offset+limit)
      songs = [Song(composer="Kevin_%04d" % i, key_name="s1234_%04d" % i)
               for i in range(offset, limit+offset)]
      db.put(songs)
      logging.debug("song key: done.")

  @classmethod
  def put_em_in(cls, limit, offset=0):
      if settings.bring_in_stubs:
          logging.debug("putting 1000")
          cls.put_xxx(limit, offset)
          logging.debug("done. putting")


  @classmethod
  def put_1000(cls):
      logging.debug("put_xxx 1000")
      cls.put_xxx(1000,0)

  @classmethod
  def put_1(cls):
      logging.debug("put_xxx 250")
      cls.put_xxx(250,0)
      
  @classmethod
  def put_2(cls):
      cls.put_xxx(250,250)

  @classmethod
  def put_3(cls):
      cls.put_xxx(250,500)

  @classmethod
  def put_4(cls):
      cls.put_xxx(250,750)

logging.debug("IMPORT settings")
import settings

if settings.bring_in_stubs:
    logging.debug("putting")
#    IndexTest.put_1()
#    IndexTest.put_2()
#    IndexTest.put_3()
#    IndexTest.put_4()
    logging.debug("done. putting")



from google.appengine.api.datastore import Query, Iterator
from asynctools import AsyncMultiTask, QueryTask, CountTask, CachedMultiTask, DatastoreDeleteTask, DatastoreGetTask
from asynctools import DatastorePutTask

from google.appengine.api import memcache

import random

from time import time

import logging

DEADLINE = 3

class AsyncTaskTest(unittest.TestCase):

  def setUp(self):
      if settings.bring_in_stubs:
          logging.debug("putting 1000")
          IndexTest.put_1000()
          logging.debug("done. putting")
          self.flush_memcache()

  def flush_memcache(self):
      mc = memcache.Client()
      mc.flush_all()


  def test_query_cache_key(self):
      query = Query('Song')
      query['composer >='] = "Kevin_0034"
      key = QueryTask(query, limit=10).cache_key
      self.assertEquals("QueryTask,query={'composer >=': 'Kevin_0034'},limit=10,offset=None", key)

  def test_count_cache_key(self):
      query = Query('Song')
      query['composer >='] = "Kevin_0034"
      key = CountTask(query, limit=10).cache_key
      self.assertEquals("CountTask,query={'composer >=': 'Kevin_0034'},limit=10,offset=None", key)

  def test_query_cache_key_md5ed(self):
      """This doesn't md5"""
      query = Query('Song')
      query['composer >='] = "Kevin_0034_" \
      "10........20........30........40........50........" \
      "60........70........80........90........100......." \
      "110.......120.......130.......140.......150......." \
      "160.......170.......180.......190.......200......."

      key = QueryTask(query, limit=10).cache_key

      expected = "QueryTask,query={'composer >=': 'Kevin_0034_" \
      "10........20........30........40........50........" \
      "60........70........80........90........100......." \
      "110.......120.......130.......140.......150......." \
      "160.......170.......180.......190.......200......." \
      "'},limit=10,offset=None"

      self.assertEquals(expected, key)

  def test_query_cache_key(self):
      query = Query('Song')
      query['composer >='] = "Kevin_0034"
      key = QueryTask(query, limit=10).cache_key
      self.assertEquals("QueryTask,query={'composer >=': 'Kevin_0034'},limit=10,offset=None", key)


  def test_gqlquery_returns_cachekey(self):
      query = Song.gql("WHERE composer >= :1", 'Mozart')
      task = QueryTask(query, limit=1)
      logging.debug("Task.cache_key:%s", task.cache_key)
      self.assertEquals("QueryTask,query={'composer >=': 'Mozart'},limit=1,offset=None", task.cache_key)


  def test_one_query_callback(self):
      def createCallback():
          def callback(task):
              logging.debug("Called Callback %r" + task.Get())
          return callback

      context = AsyncMultiTask()
      query = Query('Song')
      query['composer >='] = "Kevin_0034"
      task = QueryTask(query, limit=10, callback=createCallback())
      context.append(task)
      logging.debug("context %r", context)
      context.run()
      logging.debug("context %r", context)
      logging.debug("query %r", query)
      result = task.get_result()
      logging.debug("results %r", result)
      self.assertEqual([u'Kevin_0034', u'Kevin_0035', u'Kevin_0036', u'Kevin_0037', u'Kevin_0038', u'Kevin_0039', u'Kevin_0040', u'Kevin_0041', u'Kevin_0042', u'Kevin_0043'],
                       sorted( song.composer for song in result))

  def test_one_put_in_a_list(self):
      context = AsyncMultiTask()
      song_key = db.Key.from_path('Song', 's1234_NEW')
      song_to_put = Song(key_name='s1234_NEW', composer='New Composer')
      song_get_before_put = db.get(song_key)
      task = DatastorePutTask([song_to_put])
      context.append(task)
      context.run()
      logging.debug("context %r", context)
      logging.debug("query %r", song_key)

      key_from_put = task.get_result()
      song_get_after_put =  db.get(song_key)


      self.assertEqual([None, [song_key], song_to_put.key().name()],
                       [song_get_before_put, key_from_put, song_get_after_put.key().name()])

  def test_one_put(self):
      context = AsyncMultiTask()
      song_key = db.Key.from_path('Song', 'NoSuchEntity')
      song = db.get(song_key)
      logging.debug("song " + repr(song) )
      task = DatastoreDeleteTask([song_key])
      context.append(task)
      logging.debug("context %r", context)
      context.run()
      logging.debug("context %r", context)
      logging.debug("query %r", song_key)
      result = task.get_result()
      logging.debug("results" + repr(result))
      self.assertEqual(None,
                       result)


  def test_one_delete(self):
      context = AsyncMultiTask()
      song_key = db.Key.from_path('Song', 's1234_0035')
      song = db.get([song_key])
      logging.debug("song %s" % repr(song))
      task = DatastoreDeleteTask([song_key])
      context.append(task)
      context.run()
      logging.debug("context %r", context)
      logging.debug("query %r", song_key)

      result = task.get_result()


      logging.debug("results" + repr(result))
      song_deleted = db.get([song_key])
      logging.debug("deleted" + repr(song_deleted))

      self.assertEqual(None,
                       result)

  def test_one_delete_no_such_entity(self):
      context = AsyncMultiTask()
      song_key = db.Key.from_path('Song', 'NoSuchEntity')
      song = db.get(song_key)
      logging.debug("song " + repr(song) )
      task = DatastoreDeleteTask([song_key])
      context.append(task)
      logging.debug("context %r", context)
      context.run()
      logging.debug("context %r", context)
      logging.debug("query %r", song_key)
      result = task.get_result()
      logging.debug("results" + repr(result))
      self.assertEqual(None,
                       result)

  def test_one_get_in_a_list(self):
      context = AsyncMultiTask()
      song_key = db.Key.from_path('Song', 's1234_0035')
      song = db.get([song_key])
      logging.debug("song %s" % repr(song))
      task = DatastoreGetTask([song_key])
      context.append(task)
      context.run()
      logging.debug("context %r", context)
      logging.debug("query %r", song_key)

      result = task.get_result()


      logging.debug("results" + repr(result))
      song_deleted = db.get([song_key])
      logging.debug("deleted" + repr(song_deleted))

      self.assertEqual([{u'composer': u'Kevin_0035'}],
                       result)

  def test_one_get_in_list_return_list_of_one_None(self):
      context = AsyncMultiTask()
      song_key = db.Key.from_path('Song', 'NoSuchEntity')
      song = db.get(song_key)
      logging.debug("song " + repr(song) )
      task = DatastoreGetTask([song_key])
      context.append(task)
      logging.debug("context %r", context)
      context.run()
      logging.debug("context %r", context)
      logging.debug("query %r", song_key)
      result = task.get_result()
      logging.debug("results" + repr(result))
      self.assertEqual([None],
                       result)

  def test_one_get(self):
      context = AsyncMultiTask()
      song_key = db.Key.from_path('Song', 's1234_0035')
      task = DatastoreGetTask(song_key)
      context.append(task)
      context.run()
      logging.debug("context %r", context)
      logging.debug("query %r", song_key)

      result = task.get_result()


      logging.debug("results" + repr(result))
      song_gotten = db.get([song_key])
      logging.debug("gotten" + repr(song_gotten))

      self.assertEqual({u'composer': u'Kevin_0035'},
                       result)

  def test_one_get_in_list_return_list_of_one_None(self):
      context = AsyncMultiTask()
      song_key = db.Key.from_path('Song', 'NoSuchEntity')
      task = DatastoreGetTask(song_key)
      context.append(task)
      logging.debug("context %r", context)
      context.run()
      logging.debug("context %r", context)
      logging.debug("query %r", song_key)
      self.assertRaises(db.EntityNotFoundError, task.get_result)

  def test_one_query_memcache(self):
      context = CachedMultiTask()
      query = Query('Song')
      query['composer >='] = "Kevin_0034"
      task = QueryTask(query, limit=20)
      context.append(task)
      logging.debug("context %r", context)
      context.run()
      logging.debug("context %r", context)
      logging.debug("query " + repr(query))
      result = task.get_result()
      logging.debug("results" + repr(result))
      self.assertEqual([u'Kevin_0034', u'Kevin_0035', u'Kevin_0036', u'Kevin_0037', u'Kevin_0038', u'Kevin_0039', u'Kevin_0040', u'Kevin_0041', u'Kevin_0042', u'Kevin_0043', u'Kevin_0044', u'Kevin_0045', u'Kevin_0046', u'Kevin_0047', u'Kevin_0048', u'Kevin_0049', u'Kevin_0050', u'Kevin_0051', u'Kevin_0052', u'Kevin_0053'],
                       sorted( song.composer for song in result))

  def test_one_query_filter(self):
      context = AsyncMultiTask()

      query = Song.all().filter('composer >=', 'Kevin_0034')
      task = QueryTask(query, limit=10)
      context.append(task)
      logging.debug("context %r", context)
      context.run()
      logging.debug("context %r", context)
      logging.debug("query " + repr(query))
      result = task.get_result()
      logging.debug("results" + repr(result))
      self.assertEqual([u'Kevin_0034', u'Kevin_0035', u'Kevin_0036', u'Kevin_0037', u'Kevin_0038', u'Kevin_0039', u'Kevin_0040', u'Kevin_0041', u'Kevin_0042', u'Kevin_0043'],
                       sorted( song.composer for song in result))

  def test_one_query_filter_returns_dbModels(self):

      context = AsyncMultiTask()

      query = Song.all().filter('composer >=', 'Kevin_0034')
      task = QueryTask(query, limit=1)
      context.append(task)
      logging.debug("context %r", context)
      context.run()
      logging.debug("context %r", context)
      logging.debug("query " + repr(query))
      result = task.get_result()
      logging.debug("results" + repr(result))
      self.assertEqual([Song], [ type(r) for r in result])

  def test_one_gqlquery(self):
      context = AsyncMultiTask()
      query = Query('Song')
      query['composer >='] = "Kevin_0034"

      query = Song.gql('WHERE composer >= :1', 'Kevin_0034')
      task = QueryTask(query, limit=10)
      context.append(task)
      logging.debug("context %r", context)
      context.run()
      logging.debug("context %r", context)
      logging.debug("query " + repr(query))
      result = task.get_result()
      logging.debug("results" + repr(result))
      self.assertEqual([u'Kevin_0034', u'Kevin_0035', u'Kevin_0036', u'Kevin_0037', u'Kevin_0038', u'Kevin_0039', u'Kevin_0040', u'Kevin_0041', u'Kevin_0042', u'Kevin_0043'],
                       sorted( song.composer for song in result))

  def test_one_gqlquery_returns_dbModels(self):
      
      context = AsyncMultiTask()

      query = Song.gql('WHERE composer >= :1', 'Kevin_0034')
      task = QueryTask(query, limit=1)
      context.append(task)
      logging.debug("context %r", context)
      context.run()
      logging.debug("context %r", context)
      logging.debug("query " + repr(query))
      result = task.get_result()
      logging.debug("results" + repr(result))
      self.assertEqual([Song], [ type(r) for r in result])


  def test_one_query(self):
      context = AsyncMultiTask()
      query = Query('Song')
      query['composer >='] = "Kevin_0034"
      task = QueryTask(query, limit=10)
      context.append(task)
      logging.debug("context %r", context)
      context.run()
      logging.debug("context %r", context)
      logging.debug("query " + repr(query))
      result = task.get_result()
      logging.debug("results" + repr(result))
      self.assertEqual([u'Kevin_0034', u'Kevin_0035', u'Kevin_0036', u'Kevin_0037', u'Kevin_0038', u'Kevin_0039', u'Kevin_0040', u'Kevin_0041', u'Kevin_0042', u'Kevin_0043'],
                       sorted( song.composer for song in result))

  def test_one_query_deadline_0001(self):
      context = AsyncMultiTask()
      query = Query('Song')
      query['composer >='] = "Kevin_0034"
      task = QueryTask(query, limit=10, deadline=0.0001)
      context.append(task)
      logging.debug("context %r", context)
      context.run()
      logging.debug("context %r", context)
      logging.debug("query " + repr(query))
      result = task.get_result()
      logging.debug("results" + repr(result))
      self.assertEqual([u'Kevin_0034', u'Kevin_0035', u'Kevin_0036', u'Kevin_0037', u'Kevin_0038', u'Kevin_0039', u'Kevin_0040', u'Kevin_0041', u'Kevin_0042', u'Kevin_0043'],
                       sorted( song.composer for song in result))

  def test_one_query_deadline_001(self):
      context = AsyncMultiTask()
      query = Query('Song')
      query['composer >='] = "Kevin_0034"
      task = QueryTask(query, limit=10, deadline=0.001)
      context.append(task)
      logging.debug("context %r", context)
      context.run()
      logging.debug("context %r", context)
      logging.debug("query " + repr(query))
      result = task.get_result()
      logging.debug("results" + repr(result))
      self.assertEqual([u'Kevin_0034', u'Kevin_0035', u'Kevin_0036', u'Kevin_0037', u'Kevin_0038', u'Kevin_0039', u'Kevin_0040', u'Kevin_0041', u'Kevin_0042', u'Kevin_0043'],
                       sorted( song.composer for song in result))


  def test_one_query_deadline_01(self):
      context = AsyncMultiTask()
      query = Query('Song')
      query['composer >='] = "Kevin_0034"
      task = QueryTask(query, limit=10, deadline=0.01)
      context.append(task)
      logging.debug("context %r", context)
      context.run()
      logging.debug("context %r", context)
      logging.debug("query " + repr(query))
      result = task.get_result()
      logging.debug("results" + repr(result))
      self.assertEqual([u'Kevin_0034', u'Kevin_0035', u'Kevin_0036', u'Kevin_0037', u'Kevin_0038', u'Kevin_0039', u'Kevin_0040', u'Kevin_0041', u'Kevin_0042', u'Kevin_0043'],
                       sorted( song.composer for song in result))

  def test_one_query_deadline_02(self):
      context = AsyncMultiTask()
      query = Query('Song')
      query['composer >='] = "Kevin_0034"
      task = QueryTask(query, limit=10, deadline=0.02)
      context.append(task)
      logging.debug("context %r", context)
      context.run()
      logging.debug("context %r", context)
      logging.debug("query " + repr(query))
      result = task.get_result()
      logging.debug("results" + repr(result))
      self.assertEqual([u'Kevin_0034', u'Kevin_0035', u'Kevin_0036', u'Kevin_0037', u'Kevin_0038', u'Kevin_0039', u'Kevin_0040', u'Kevin_0041', u'Kevin_0042', u'Kevin_0043'],
                       sorted( song.composer for song in result))


  def test_one_query_deadline_03(self):
      context = AsyncMultiTask()
      query = Query('Song')
      query['composer >='] = "Kevin_0034"
      task = QueryTask(query, limit=10, deadline=0.03)
      context.append(task)
      logging.debug("context %r", context)
      context.run()
      logging.debug("context %r", context)
      logging.debug("query " + repr(query))
      result = task.get_result()
      logging.debug("results" + repr(result))
      self.assertEqual([u'Kevin_0034', u'Kevin_0035', u'Kevin_0036', u'Kevin_0037', u'Kevin_0038', u'Kevin_0039', u'Kevin_0040', u'Kevin_0041', u'Kevin_0042', u'Kevin_0043'],
                       sorted( song.composer for song in result))

  def test_one_query_deadline_1(self):
      context = AsyncMultiTask()
      query = Query('Song')
      query['composer >='] = "Kevin_0034"
      task = QueryTask(query, limit=10, deadline=0.1)
      context.append(task)
      logging.debug("context %r", context)
      context.run()
      logging.debug("context %r", context)
      logging.debug("query " + repr(query))
      result = task.get_result()
      logging.debug("results" + repr(result))
      self.assertEqual([u'Kevin_0034', u'Kevin_0035', u'Kevin_0036', u'Kevin_0037', u'Kevin_0038', u'Kevin_0039', u'Kevin_0040', u'Kevin_0041', u'Kevin_0042', u'Kevin_0043'],
                       sorted( song.composer for song in result))


  def datastore_count_async(self,NUMBER_QUERIES=175,NUMBER_RESULTS=50,callback=None):
    logging.debug("Async DB:" +self.id())
    IndexTest.put_em_in(NUMBER_QUERIES+NUMBER_RESULTS)
    start = time()

    def createSongQuery(composer):
        query = Query('Song')#random.uniform(0.03,0.075))
        query['composer >='] = composer
        songquery = CountTask(query, limit=NUMBER_RESULTS, deadline=DEADLINE, callback=callback)
        return songquery


    composerstoquery = ["Kevin_%04d" % x for x in range(1000)[:NUMBER_QUERIES]]
    logging.debug("composers: " + repr(composerstoquery))

    songs = [ createSongQuery(composer) for composer in composerstoquery]

    context  = AsyncMultiTask(songs)

    logging.debug("context Run" + repr(context))
    context.run()


    logging.debug("songs " + repr(songs))
    sumnum = sum(query.get_result() for query in songs)

    logging.debug("sumnum: "+str(sumnum))

    def logSong(songs):
        logging.debug("song xml "+ str([entity.ToXml() for entity in songs]))
        composer = [Song.from_entity(entity).composer for entity in songs]
        logging.debug("str"+ repr(composer))
        return composer
#    composers = map(logSong, songs)

    end = time()
    logging.info('Composer QUERIESxRESULTS=%dx%d time=%0.3f qty=%d ' % (NUMBER_QUERIES, NUMBER_RESULTS, end - start, sumnum))
    self.assertEqual(NUMBER_QUERIES*NUMBER_RESULTS, sumnum)
      


  def datastore_get_async(self,NUMBER_QUERIES=175,NUMBER_RESULTS=50,callback=None):
    logging.debug("Async DB:" +self.id())
    IndexTest.put_em_in(NUMBER_QUERIES+NUMBER_RESULTS)
    start = time()

    def createSongQuery(composer):
        query = Query('Song')#random.uniform(0.03,0.075))
        query['composer >='] = composer
        songquery = QueryTask(query, limit=NUMBER_RESULTS, deadline=DEADLINE, callback=callback)
        return songquery


    composerstoquery = ["Kevin_%04d" % x for x in range(1000)[:NUMBER_QUERIES]]
    logging.debug("composers: " + repr(composerstoquery))

    songs = [ createSongQuery(composer) for composer in composerstoquery]

    context  = AsyncMultiTask(songs)

    logging.debug("context Run" + repr(context))
    context.run()


    logging.debug("songs " + repr(songs))
    sumnum = sum(map(len,[query.get_result() for query in songs]))

    logging.debug("sumnum: "+str(sumnum))

    def logSong(songs):
        logging.debug("song xml "+ str([entity.ToXml() for entity in songs]))
        composer = [Song.from_entity(entity).composer for entity in songs]
        logging.debug("str"+ repr(composer))
        return composer
#    composers = map(logSong, songs)

    end = time()
    logging.info('Composer QUERIESxRESULTS=%dx%d time=%0.3f qty=%d ' % (NUMBER_QUERIES, NUMBER_RESULTS, end - start, sumnum))
    self.assertEqual(NUMBER_QUERIES*NUMBER_RESULTS, sumnum)

  def datastore_get_sync(self,NUMBER_QUERIES=175,NUMBER_RESULTS=50):
    IndexTest.put_em_in(NUMBER_QUERIES+NUMBER_RESULTS)


    logging.debug("Sync DB:" +self.id())
    songquery = []
    runqueryrpc = []

    start = time()

    def createSongQuery(composer):
        songquery = Query('Song')
        songquery['composer >='] = composer
        return songquery.Get(NUMBER_RESULTS)

    composerstoquery = ["Kevin_%04d" % x for x in range(1000)[:NUMBER_QUERIES]]
    logging.debug("composers: " + repr(composerstoquery))

    songs = map(createSongQuery, composerstoquery)

    sumnum = sum(map(len,songs))

    logging.debug("sumnum: "+str(sumnum))
    #    song = sq.Get(100)
    def logSong(songs):
        logging.debug("song xml "+ str([song.ToXml() for song in songs]))
        composer = [Song.from_entity(song).composer for song in songs]
        logging.debug("str"+ repr(composer))
        return composer
#    composers = map(logSong, songs)

    end = time()

    logging.info('composer QUERIESxRESULTS=%dx%d time=%0.3f qty=%d' % (NUMBER_QUERIES, NUMBER_RESULTS, end - start, sumnum))
    self.assertEqual(NUMBER_QUERIES*NUMBER_RESULTS, sumnum)

  def test_count_async_10_2(self):
    def createCallback():
          def callback(task):
              logging.debug("Called Callback " + repr(task))
          return callback
    self.datastore_count_async(10,2,callback=createCallback())

  def test_count_async_1_750(self):
    def createCallback():
          def callback(task):
              logging.debug("Called Callback " + repr(task))
          return callback

    self.datastore_count_async(1,750, callback=createCallback())

  def test_count_async_25_25(self):
    self.datastore_count_async(25,25)

  def test_count_async_1_100(self):
    self.datastore_count_async(1,100)

  def test_count_async_100_1(self):
    self.datastore_count_async(100,1)

  def test_count_async_100_25(self):
    self.datastore_count_async(100,25)

  def test_count_async_750_25(self):
    self.datastore_count_async(750,25)

  def test_count_async_40_100(self):
    self.datastore_count_async(40,100)

  def datastore_get_sync(self,NUMBER_QUERIES=175,NUMBER_RESULTS=50):
    IndexTest.put_em_in(NUMBER_QUERIES+NUMBER_RESULTS)


    logging.debug("Sync DB:" +self.id())
    songquery = []
    runqueryrpc = []

    start = time()

    def createSongQuery(composer):
        songquery = Query('Song')
        songquery['composer >='] = composer
        return songquery.Get(NUMBER_RESULTS)

    composerstoquery = ["Kevin_%04d" % x for x in range(1000)[:NUMBER_QUERIES]]
    logging.debug("composers: " + repr(composerstoquery))

    songs = map(createSongQuery, composerstoquery)

    sumnum = sum(map(len,songs))

    logging.debug("sumnum: "+str(sumnum))
    #    song = sq.Get(100)
    def logSong(songs):
        logging.debug("song xml "+ str([song.ToXml() for song in songs]))
        composer = [Song.from_entity(song).composer for song in songs]
        logging.debug("str"+ repr(composer))
        return composer
#    composers = map(logSong, songs)

    end = time()

    logging.info('composer QUERIESxRESULTS=%dx%d time=%0.3f qty=%d' % (NUMBER_QUERIES, NUMBER_RESULTS, end - start, sumnum))
    self.assertEqual(NUMBER_QUERIES*NUMBER_RESULTS, sumnum)


  def test_async_10_2(self):
    def createCallback():
          def callback(task):
              logging.debug("Called Callback " + repr(task.Get()))
          return callback
    self.datastore_get_async(10,2,callback=createCallback())

  def test_sync_10_2(self):
    self.datastore_get_sync(10,2)

#  def test_async_100_100(self):
#    self.datastore_get_async(100,100)
#
#  def test_sync_100_100(self):
#    self.datastore_get_sync(100,100)
#
#  def test_async_150_50(self):
#    self.datastore_get_async(150,50)
#
#  def test_sync_150_50(self):
#    self.datastore_get_sync(150,50)

  def test_async_1_750(self):
    def createCallback():
          def callback(task):
              logging.debug("Called Callback " + repr(task.Get()))
          return callback

    self.datastore_get_async(1,750, callback=createCallback())

  def test_sync_1_750(self):
    self.datastore_get_sync(1,750)

#  def test_async_750_1(self):
#    self.datastore_get_async(750,1)

#  def test_sync_750_1(self):
#    self.datastore_get_sync(750,1)

  def test_async_25_25(self):
    self.datastore_get_async(25,25)

  def test_sync_25_25(self):
    self.datastore_get_sync(25,25)

  def test_async_1_100(self):
    self.datastore_get_async(1,100)

  def test_sync_1_100(self):
    self.datastore_get_sync(1,100)

  def test_async_100_1(self):
    self.datastore_get_async(100,1)
#
#  def test_sync_100_1(self):
#    self.datastore_get_sync(100,1)
#
  def test_async_100_25(self):
    self.datastore_get_async(100,25)
#
#  def test_sync_100_25(self):
#    self.datastore_get_sync(100,25)

#
class CachedMultiTaskTest(unittest.TestCase):
  def setUp(self):
        if settings.bring_in_stubs:
            logging.debug("putting 1000")
            IndexTest.put_1000()
            logging.debug("done. putting")
            self.flush_memcache()

  def flush_memcache(self):
        mc = memcache.Client()
        mc.flush_all()


  def test_one_query_memcache(self):
      context = CachedMultiTask()
      query = Query('Song')
      query['composer >='] = "Kevin_0034"
      task = QueryTask(query, limit=20)
      context.append(task)
      logging.debug("context %r", context)
      context.run()
      logging.debug("context %r", context)
      logging.debug("query " + repr(query))
      result = task.get_result()
      logging.debug("results" + repr(result))
      self.assertEqual([u'Kevin_0034', u'Kevin_0035', u'Kevin_0036', u'Kevin_0037', u'Kevin_0038', u'Kevin_0039', u'Kevin_0040', u'Kevin_0041', u'Kevin_0042', u'Kevin_0043', u'Kevin_0044', u'Kevin_0045', u'Kevin_0046', u'Kevin_0047', u'Kevin_0048', u'Kevin_0049', u'Kevin_0050', u'Kevin_0051', u'Kevin_0052', u'Kevin_0053'],
                       sorted( song.composer for song in result ))


  def test_one_query(self):
      context = CachedMultiTask()
      query = Query('Song')
      query['composer >='] = "Kevin_0034"
      task = QueryTask(query, limit=10)
      context.append(task)
      logging.debug("context %r", context)
      context.run()
      logging.debug("context %r", context)
      logging.debug("query %r", query)
      result = task.get_result()
      logging.debug("results %r", result)
      self.assertEqual([u'Kevin_0034', u'Kevin_0035', u'Kevin_0036', u'Kevin_0037', u'Kevin_0038', u'Kevin_0039', u'Kevin_0040', u'Kevin_0041', u'Kevin_0042', u'Kevin_0043'],
                       sorted( song.composer for song in result))



  def datastore_get_async(self,NUMBER_QUERIES=175,NUMBER_RESULTS=50, callback=None):
    logging.debug("Cached Async DB:%s", self.id())
    IndexTest.put_em_in(NUMBER_QUERIES+NUMBER_RESULTS)

    start = time()

    def createSongQuery(composer):
        query = Query('Song')#random.uniform(0.03,0.075))
        query['composer >='] = composer
        songquery = QueryTask(query, limit=NUMBER_RESULTS, callback=callback, deadline=DEADLINE)
        return songquery


    composerstoquery = ["Kevin_%04d" % x for x in range(1000)[:NUMBER_QUERIES]]
    logging.debug("composers: %r", composerstoquery)

    songs = [ createSongQuery(composer) for composer in composerstoquery]

    context  = CachedMultiTask(songs)

    logging.debug("context Run %r", context)
    context.run()


    logging.debug("songs %r", songs)
    sumnum = sum(map(len,[query.get_result() for query in songs]))

    logging.debug("sumnum: %s", sumnum)

    def logSong(songs):
        logging.debug("song xml %s", str([entity.ToXml() for entity in songs]))
        composer = [Song.from_entity(entity).composer for entity in songs]
        logging.debug("str %r", composer)
        return composer
#    composers = map(logSong, songs)

    end = time()

    logging.debug('composer QUERIES_RESULTS=%dx%d time=%0.3f qty=%d ', NUMBER_QUERIES, NUMBER_RESULTS, end - start, sumnum)
    self.assertEqual(NUMBER_QUERIES*NUMBER_RESULTS, sumnum)


  def datastore_count_async(self,NUMBER_QUERIES=175,NUMBER_RESULTS=50, callback=None):
    logging.debug("Cached Async DB:%s", self.id())
    IndexTest.put_em_in(NUMBER_QUERIES+NUMBER_RESULTS)

    start = time()

    def createSongQuery(composer):
        query = Query('Song')#random.uniform(0.03,0.075))
        query['composer >='] = composer
        songquery = CountTask(query, limit=NUMBER_RESULTS, callback=callback, deadline=DEADLINE)
        return songquery

    composerstoquery = ["Kevin_%04d" % x for x in range(1000)[:NUMBER_QUERIES]]
    songs = [ createSongQuery(composer) for composer in composerstoquery]

    context  = CachedMultiTask(songs)

    logging.debug("context Run%r", context)
    context.run()


    logging.debug("songs %r", songs)
    sumnum = sum(query.get_result() for query in songs)

    logging.debug("sumnum: %s", sumnum)

    def logSong(songs):
        logging.debug("song xml %s", str([entity.ToXml() for entity in songs]))
        composer = [Song.from_entity(entity).composer for entity in songs]
        logging.debug("str %r", composer)
        return composer
#    composers = map(logSong, songs)

    end = time()

    logging.debug('composer QUERIES_RESULTS=%dx%d time=%0.3f qty=%d ', NUMBER_QUERIES, NUMBER_RESULTS, end - start, sumnum)
    self.assertEqual(NUMBER_QUERIES*NUMBER_RESULTS, sumnum)


  def test_count_async_10_2(self):
    def createCallback():
          def callback(task):
              logging.debug("Called Callback %r", task)
          return callback
    self.datastore_count_async(10,2,callback=createCallback())

  def test_count_async_1_750(self):
    def createCallback():
          def callback(task):
              logging.debug("Called Callback %r",  task)
          return callback

    self.datastore_count_async(1,750, callback=createCallback())

  def test_count_async_25_25(self):
    self.datastore_count_async(25,25)

  def test_count_async_1_100(self):
    self.datastore_count_async(1,100)

  def test_count_async_100_1(self):
    self.datastore_count_async(100,1)

  def test_count_async_100_25(self):
    self.datastore_count_async(100,25)

  def test_count_async_750_25(self):
    self.datastore_count_async(750,25)

  def test_count_async_40_100(self):
    self.datastore_count_async(40,100)


  def test_async_10_2(self):
    def createCallback():
          def callback(task):
              logging.debug("Called Callback %r", task.Get())
          return callback
    self.datastore_get_async(10,2,callback=createCallback())

#  def test_async_100_100(self):
#    self.datastore_get_async(100,100)
#
#  def test_async_150_50(self):
#    self.datastore_get_async(150,50)

  def test_async_1_750(self):
    def createCallback():
          def callback(task):
              logging.debug("Called Callback %r", task.Get())
          return callback

    self.datastore_get_async(1,750, callback=createCallback())

#  def test_async_750_1(self):
#    self.datastore_get_async(750,1)

  def test_async_25_25(self):
    self.datastore_get_async(25,25)

  def test_async_1_100(self):
    self.datastore_get_async(1,100)

#  def test_async_100_1(self):
#    self.datastore_get_async(100,1)
#
#  def test_async_100_25(self):
#    self.datastore_get_async(100,25)
#
